/**
 * @公司:公约树
 * @位置:苏州
 * @Classname AnimeHoverProperty
 * @Date 2022-06-27 下午 10:51
 * @Created by hanWanLu
 * @auther 中文:韩万路
 */


package com.animeJava.mode.animeModel;

import com.animeJava.core.AnimeCore;
import com.animeJava.core.EasingData;
import com.animeJava.dao.animeEvent.AnimeEventFinal;
import com.animeJava.dao.animeEvent.AnimeRender;
import com.animeJava.data.KeyData;
import com.animeJava.enumData.DirectionEnum;
import com.animeJava.enumData.EasingDataEnum;
import com.animeJava.mode.AnimeModel;
import com.animeJava.mode.AnimeRunStart;
import com.animeJava.mode.PositionVarModel;
import com.animeJava.util.AnimeException;

import java.util.*;

/**
 * 动画过度效果
 */
public class AnimeHoverProperty extends AnimeModel {
    private Double[]        inData      ;               //输入数据
    private Double[]        toData      ;               //到数据
    private long            duration    =   1000;	 //持续时间 单位毫秒	number, function (el, index, total)
    private EasingData      easing      =   EasingDataEnum.EASE_IN_OUT.getData();  //easing	'easeOutElastic'	console log anime.easings to get the complete functions list
    private static AnimeCore animeCore = new AnimeCore();   //动画曲线计算

    public AnimeHoverProperty() {
    }
    public AnimeHoverProperty(HashMap<String , Object> params) {
        super(params);
        if(params != null){
            Set<Map.Entry<String, Object>> entries = params.entrySet();
            for (Map.Entry<String, Object> map: entries) {
                if("easing".equals(map.getKey()) && map.getValue() != null){
                    this.easing = (EasingData) map.getValue();
                    break;
                }
                if("duration".equals(map.getKey()) && map.getValue() != null){
                    this.duration = (long) map.getValue();
                }
            }
        }
    }
    public AnimeHoverProperty(long delay, long duration, boolean autoplay, boolean loop, DirectionEnum direction, EasingData easing, AnimeEventFinal begin, AnimeRender update, AnimeEventFinal complete) {
        super(delay,autoplay,loop,direction,begin,complete);

        this.duration = duration;
        this.easing = easing;

    }


    @Override
    public long animeFactory(long animeKey , int FPS , AnimeRunStart animeRunStart,
                             AnimeEventFinal begin, AnimeRender update, AnimeEventFinal complete) throws AnimeException {

        //是多少次才可开始执行动画
        long delayFrequency = this.getDelay() / FPS;
        //当前动画有多少次的执行中时间
        long durationFrequency = this.getDuration() / FPS;
        //获取当前的帧数大于延时的时间后的帧数;
        double k = (animeKey - delayFrequency);
        //获取当前是否是来回的状态
        DirectionEnum direction = this.getDirection();
        //当下获取贝塞尔曲线的图
        EasingData easing = this.getEasing();
        //获取当前动画执行到了百分之几了
        double thisPath = 0;
        switch (direction){
            case NORMAL:{   //正常
                thisPath = k / durationFrequency;
                break;
            }
            case REVERSE:{  //倒叙
                thisPath = 1 - (k / durationFrequency );
                break;
            }
            case ALTERNATE:{    //来回
                thisPath = (k / durationFrequency >= 0.5? 0.5 - (k / durationFrequency - 0.5):k / durationFrequency )*2;
                break;
            }
        }

        //插入当前时间的百分比
        animeRunStart.setPathPercentage(thisPath);

        //********************动画延时后开始执行****************************//
        //如果当前是延时后的动画 并且动画还未开始
        if(animeKey > delayFrequency && animeRunStart.getRunStart() == 0){
            animeRunStart.setRunStart(1);
            //动画开始执行
            if(this.getBegin() != null){
                //如果run报错则清空当前的动画
                this.getBegin().run("");
            }
            if(begin != null) {
                begin.run("动画开始执行");
                animeRunStart.setUse(true);
            }
        }
        //********************动画延时后执行中****************************//
//        try{
//            update.run(0D,null, Arrays.asList(inData));
//        }catch (Exception e){
//            return 0;
//        }
        //当前的帧数大于延时的时间  并且 小于 延时时间加上 总共时间数 并且动画是在开始之中
        if(animeKey >= delayFrequency && animeKey <= delayFrequency+ durationFrequency && animeKey != 0  ){
            renderer(thisPath, new AnimeRender() {
                @Override
                public boolean run(Double timeTo, Map<String, PositionVarModel> animeInfo, List<Double> data) {
                    return update.run(timeTo,null,data);
                }
            });
        }else{
//            renderer(thisPath, new AnimeRender() {
//                @Override
//                public void run(Double timeTo, Map<String, PositionVarModel> animeInfo, List<Double> data) {
//                    update.run(timeTo,null,data);
//                }
//            });
        }

        //********************动画走完执行****************************//
        //判断当前的时间是否走完  如果走完  则判断是  否循环
        if(animeKey > delayFrequency+durationFrequency +1  && animeRunStart.getRunStart() != -1){

            animeRunStart.setRunStart(-1); //标记-1
            //动画完执行
            if(this.getComplete() != null){
                //如果run报错则清空当前的动画
                this.getComplete().run("动画执行完毕");
            }
            if(complete != null)complete.run("动画执行完毕");
            //并且判断是否循环
            if(this.isLoop()){
                animeKey = 0; //从新执行了
                animeRunStart.setRunStart(0); //标记 0 开始
            }
        }else{
            //每一帧的执行
            //这里控制动画的百分比
            //没走完接着走
            if(animeRunStart.getRunStart() != -1){
                animeKey++;
            }
            //判断当前是否是自动播放如果是自动播放则自动修改为0
            if(animeRunStart.getRunStart() == -1){
                if(this.isLoop()){
                    animeRunStart.setRunStart(0);
                }
                //是手动控制并且不是循环则执行当前
                if(!this.isLoop()){
                    animeKey = (long) ((delayFrequency+durationFrequency)*animeRunStart.getAnimeKeyV2());
                }
            }
        }
        return animeKey;

    }

    private void renderer(Double thisPath , AnimeRender update ) throws AnimeException {
        //如果run报错则清空当前的动画
        Map<String, PositionVarModel> core = animeCore.core(easing, thisPath);
        Double finalPositionY = core.get("finalPosition").getY();

        /**
         * in数据为空 或者 to数据为空则不执行
         */
        if(inData == null || toData == null){
            return;
        }
        List<Double> runData = new ArrayList<Double>(inData.length);    //执行解析后的数据
        for (int i = 0; i < inData.length; i++) {
            Double inDatum = inData[i];
            Double toDatum = toData[i];
            double v = inDatum + (toDatum - inDatum) * finalPositionY;
            runData.add(v);
        }


        //赋值执行
        if(update != null &&  runData != null && runData.size() != 0 ){
            update.run(thisPath,null,runData);
            this.setKeyData(new KeyData<Double>(thisPath , runData));
        }
    }


    public EasingData getEasing() {
        return easing;
    }

    public void setEasing(EasingData easing) {
        this.easing = easing;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

    private void setKeyData(KeyData<Double> keyData){
        this.updateKeyData(keyData);
    }

    /**
     * 到什么位置只有此包中方可访问
     * @param keyData
     */
    public void toPosition(Double... keyData){
        this.toData = keyData;
    }
    /**
     * 到什么位置只有此包中方可访问
     * @param keyData
     */
    public void inPosition(Double... keyData){
        this.inData = keyData;
    }

}
